#include "CAcademyBossMgr.h"
#include "MsgBattle.pb.h"
#include "MsgAcademyBoss.pb.h"
#include "commmsg.h"
#include "../simpleconfig/CMonsterConfig.h"
#include "../data/CPlayerCacheData.h"
#include "../status/CUserStatus.h"
#include "../boss/CWorldBossCfg.h"
#include "../battle/CBattleData.h"
#include "../battle/CBattleRole.h"
#include "../battle/CBattleMgr.h"
#include "../map/CMapView.h"
#include "../mainctrl.h"
#include "CTRandomNum.h"
#include "MsgGM.pb.h"

/************************************************
*学院BOSS场景地图ID不需要存储DB 掉线需要重进入
************************************************/
bool CAcademyBossMgr::IsMapIDNeedUpdateDB(const unsigned int uiMapID)
{
#if 0
    if (GetAcademyBossMapID(ACADEMY_TYPE_GRAN) == uiMapID ||
        GetAcademyBossMapID(ACADEMY_TYPE_SLEN) == uiMapID ||
        GetAcademyBossMapID(ACADEMY_TYPE_RAVAN) == uiMapID ||
        GetAcademyBossMapID(ACADEMY_TYPE_HUFF) == uiMapID)
    {
        return false;
    }
#endif
    if (GetAcademyBossMapID(ACADEMY_TYPE_GRAN) == uiMapID ||
        GetAcademyBossMapID(ACADEMY_TYPE_SLEN) == uiMapID)
    {
        return false;
    }

    return true;
}

int CAcademyBossMgr::CheckRoleEnterAndBattle(CPlayerBaseInfo& stPlayerBase,
        int iEnterAcademy)
{
    int iIndex = 0;
    int iRoleAcademy = stPlayerBase._ucAcademy;
    int iAttackAcademy = 0;

    if (!IsValidAcademyType(iEnterAcademy))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    if (!IsValidAcademyType(iRoleAcademy))
    {
    	return ERROR_ACADEMY_BOSS_NO_ACADEMY;
    }

    if (iRoleAcademy == iEnterAcademy)
    {
        return 0;
    }

    iIndex = _stRandList.FindAcademyRand(iRoleAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    if (GetMonsterHP(stAcademyMon, ENUM_ACADEMY_BOSS_MON_BOSS) > 0)
    {
        return ERROR_ACADEMY_BOSS_NO_KILL;
    }

    return 0;
}

/************************************************
*移动进入学院BOSS场景地图的处理逻辑
************************************************/
int CAcademyBossMgr::EnterScene(const unsigned int uiMapID,
        CPlayerBaseInfo& stPlayerBase)
{
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash.HashFind(stPlayerBase._uiGID);
    if (iIndex < 0)
    {
        return RET_SYS_ERROR;
    }
    CPlayerOnlineData& stPlayerOnlineData = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash[iIndex];

#if 0
    if (GetAcademyBossMapID(ACADEMY_TYPE_GRAN) != uiMapID &&
        GetAcademyBossMapID(ACADEMY_TYPE_SLEN) != uiMapID &&
        GetAcademyBossMapID(ACADEMY_TYPE_RAVAN) != uiMapID &&
        GetAcademyBossMapID(ACADEMY_TYPE_HUFF) != uiMapID)
    {
        return 0;
    }
#endif
    if (GetAcademyBossMapID(ACADEMY_TYPE_GRAN) != uiMapID &&
        GetAcademyBossMapID(ACADEMY_TYPE_SLEN) != uiMapID)
    {
        return 0;
    }

    //检查系统是否开启
    if (!CMainCtrl::m_pstMain->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_32, stPlayerBase, stPlayerOnlineData))
    {
        return ERROR_SYS_NOT_OPEN;
    }

    if (CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(uiMapID,
            stPlayerBase._uiGID))
    {
        //已经在场景内的不限制
        return 0;
    }

    int iRet = 0;
    iIndex = 0;
    int iAcademyType = 0;

    iAcademyType = GetAcademyTypeByMapID(uiMapID);
    CT_CHECK(iAcademyType, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(stActUnit.GetActID()))
    {
        return ERROR_ACADEMY_BOSS_ACT_NO_OPEN;//非活动期间不允许进入
    }

    iRet = CheckRoleEnterAndBattle(stPlayerBase, iAcademyType);
    CT_RETURN(iRet);

    return 0;
}

/************************************************
*离开学院BOSS活动场景
************************************************/
int CAcademyBossMgr::LeaveScene()
{
    return 0;
}

/************************************************
*活动自然开启的处理逻辑
*必须通过引用的方式将活动实体传过来而不能再在内部find活动
************************************************/
int CAcademyBossMgr::ActOpen(CActCfgData& stActCfgData)
{
    int iRet = 0;
    int iIndex = 0;
    int iAcademyType = 0;
    int iAttackAcademy = 0;

    iAcademyType = GetAcademyTypeByActID(stActCfgData.GetResID());
    CT_CHECK(iAcademyType, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    //这里隐含的要求:四个学院BOSS开启时间要求一致
    int iActBeginTime = stActCfgData.GetBeginTime();
    if (iActBeginTime > _stRandList.GetLastRandTime())
    {
        _stRandList.AcademyRandom();
        _stRandList.SetLastRandTime(iActBeginTime);
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    iIndex = _stActList.FindAcademyAct(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_EMPTY_CFG);

    CActCfgData& stAttackActData =
        CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stSceneMgr.FindSceneCfg(
        stAttackActData.GetSceneID());
    CT_CHECK(iIndex, ERROR_SCENE_EMPTY_CFG);

    CSceneCfgData& stAttackSceneData =
        CMainCtrl::m_pstMain->m_stSceneMgr.GetSceneCfg(iIndex);

    stAcademyMon.Clear();

    stAcademyMon.SetEndTime(stActCfgData.GetEndTime());

    stAcademyMon.SetBossMonGroupID(stAttackSceneData.GetMonGroupID());
    stAcademyMon.SetLeftMonGroupID(stAttackSceneData.GetLeftGroupID());
    stAcademyMon.SetRightMonGroupID(stAttackSceneData.GetRightGroupID());

    stAcademyMon.SetWorldLevel(
        CMainCtrl::m_pstMain->m_stArenaMgr.GetWorldBossLevel());

    stAcademyMon.SetMonBornTime(
        stActCfgData.GetBeginTime() + ACADEMY_BOSS_MONSTER_BORN_TIME);

    stAcademyMon.SetBossBornTime(0);

    CMonsterGroupConfigData stMonsterGroup;

    //设置试练使者
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(
        stAcademyMon.GetBossMonGroupID(), stAcademyMon.GetWorldLevel(),
        stMonsterGroup);
    CT_RETURN(iRet);

    stAcademyMon.SetBossMonHP(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);
    stAcademyMon.SetBossMonHPMax(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);

    stAcademyMon.SetBossMonsterID(stMonsterGroup._astMonsters[0]._uiMonsterID);

    //设置左试练侍从
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(
        stAcademyMon.GetLeftMonGroupID(), stAcademyMon.GetWorldLevel(),
        stMonsterGroup);
    CT_RETURN(iRet);

    stAcademyMon.SetLeftMonHP(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);
    stAcademyMon.SetLeftMonHPMax(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);

    stAcademyMon.SetLeftMonsterID(stMonsterGroup._astMonsters[0]._uiMonsterID);

    //设置右试练侍从
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(
        stAcademyMon.GetRightMonGroupID(), stAcademyMon.GetWorldLevel(),
        stMonsterGroup);
    CT_RETURN(iRet);

    stAcademyMon.SetRightMonHP(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);
    stAcademyMon.SetRightMonHPMax(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);

    stAcademyMon.SetRightMonsterID(stMonsterGroup._astMonsters[0]._uiMonsterID);

    CT_TRACE(("academy boss end time(%d) monster hp(%d)",
              stAcademyMon.GetEndTime(),stAcademyMon.GetBossMonHP()));

    //设置学院竞技场前三玩家
    T_ACADEMY_RANK_GID_DATA stAcademyRank;
    stAcademyRank.Clear();
    iRet = CMainCtrl::m_pstMain->m_stAcademyMgr.GetArenaRankGID(iAttackAcademy,
        stAcademyRank);
    CT_RETURN(iRet);

    MsgReqAcademyBoss stMsgReq;
    stMsgReq.set_sub_type(CMD_ACADEMY_BOSS_SUB_ROLE_INFO);
    stMsgReq.set_academy_type(iAcademyType);

#define ACADEMY_BOSS_MONSTER_NUM 3
#define ACADEMY_BOSS_BOSS_INDEX 0
#define ACADEMY_BOSS_LEFT_INDEX 1
#define ACADEMY_BOSS_RIGHT_INDEX 2

    for (int i = 0; i < stAcademyRank.Size() && i < ACADEMY_BOSS_MONSTER_NUM;
            ++i)
    {
        if (ACADEMY_BOSS_BOSS_INDEX == i)
        {
            stMsgReq.set_monster_type(ENUM_ACADEMY_BOSS_MON_BOSS);
        }
        else if (ACADEMY_BOSS_LEFT_INDEX == i)
        {
            stMsgReq.set_monster_type(ENUM_ACADEMY_BOSS_MON_LEFT);
        }
        else if (ACADEMY_BOSS_RIGHT_INDEX == i)
        {
            stMsgReq.set_monster_type(ENUM_ACADEMY_BOSS_MON_RIGHT);
        }

        stMsgReq.set_gid(stAcademyRank[i]);

        iRet = CMainCtrl::m_pstMain->SendInnerCmd(stAcademyRank[i],
            ID_MAIN_ACADEMY_BOSS, stMsgReq, false);
        if (iRet) {CT_ERROR(("send role(%u) inner cmd(%d) error(%d)",
                             stAcademyRank[i],ID_MAIN_ACADEMY_BOSS,iRet));}
    }

    CMainCtrl::m_pstMain->m_stRewardBackMgr.SetActOpen(ACT_ID_GRAN_BOSS,
        stAcademyMon.GetWorldLevel());

    return 0;
}

/************************************************
*活动自然开启设置敌对学院竞技场前三名角色为怪物
************************************************/
int CAcademyBossMgr::SetAcademyBossMonRole(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerSnsCommInfo& stPlayerSnsComm, MsgReqAcademyBoss& stReq)
{
    int iRet = 0;
    int iIndex = 0;
    int iMonsterType = stReq.monster_type();
    int iAcademyType = stReq.academy_type();
    int iAttackAcademy = 0;

    if (!IsValidMonsterType(iMonsterType))
    {
        return ERROR_ACADEMY_BOSS_MONSTER_TYPE;
    }

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(stActUnit.GetActID()))
    {
        return ERROR_ACADEMY_BOSS_ACT_NO_OPEN;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    MsgAcademyBossMonster& stMsgAcademyMon = GetMsgMonRole(stAcademyMon,
        iMonsterType);

    CPlayerEquip& stMsgRoleEquip = GetMonRoleEquip(stAcademyMon, iMonsterType);

    if (stMsgAcademyMon.has_role_info())
    {
        CT_WARNING(("academy(%d) monster(%d) has been initialized, now again!",
                    iAcademyType,iMonsterType));
    }
    
    MsgRoleInfo* pstMsgRoleInfo = stMsgAcademyMon.mutable_role_info();
    if (!pstMsgRoleInfo) {CT_WARNING(("role pointer null"));return -1;}

    iRet = CMainCtrl::m_pstMain->m_stRoleMgr.CopyRoleInfo(stPlayerBase,
        stPlayerDetail, stPlayerOnline, stPlayerSnsComm, (*pstMsgRoleInfo));
    if(iRet) {CT_WARNING(("copy role info error(%d)",iRet));return iRet;}

    iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetEquipInfo(stPlayerDetail,
        stPlayerOnline, 0, *(stMsgAcademyMon.mutable_equips()));
    if(iRet) {CT_WARNING(("copy role equip error(%d)",iRet));return iRet;}

    stMsgRoleEquip = stPlayerDetail._stPlayerEquip;

    return 0;
}

/************************************************
*活动自然关闭的处理逻辑
************************************************/
int CAcademyBossMgr::ActClose(CActCfgData& stActCfgData)
{
    int iAcademyType = 0;

    iAcademyType = GetAcademyTypeByActID(stActCfgData.GetResID());
    CT_CHECK(iAcademyType, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    //下发排名榜给场景内所有角色
    AcademyBossSceneNotify(iAcademyType);

    //发放奖励礼包
    AcademyBossFinishReward(iAcademyType);

    return 0;
}

/************************************************
*根据学院类型获取学院BOSS场景地图ID
************************************************/
unsigned int CAcademyBossMgr::GetAcademyBossMapID(int iAcademyType)
{
    int iIndex = 0;

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, 0);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    if (stActUnit.GetMapID() <= 0)
    {
        iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(
            stActUnit.GetActID());
        CT_CHECK(iIndex, 0);

        CActCfgData& stActCfgData =
            CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stSceneMgr.FindSceneCfg(
            stActCfgData.GetSceneID());
        CT_CHECK(iIndex, 0);

        CSceneCfgData& stSceneCfgData =
            CMainCtrl::m_pstMain->m_stSceneMgr.GetSceneCfg(iIndex);

        stActUnit.SetMapID(stSceneCfgData.GetMapID());
    }

    return stActUnit.GetMapID();
}

/************************************************
*根据学院BOSS场景地图ID获取学院类型
************************************************/
int CAcademyBossMgr::GetAcademyTypeByMapID(unsigned int uiMapID)
{
    if (GetAcademyBossMapID(ACADEMY_TYPE_GRAN) == uiMapID)
    {
        return ACADEMY_TYPE_GRAN;
    }
    if (GetAcademyBossMapID(ACADEMY_TYPE_SLEN) == uiMapID)
    {
        return ACADEMY_TYPE_SLEN;
    }
#if 0
    if (GetAcademyBossMapID(ACADEMY_TYPE_RAVAN) == uiMapID)
    {
        return ACADEMY_TYPE_RAVAN;
    }
    if (GetAcademyBossMapID(ACADEMY_TYPE_HUFF) == uiMapID)
    {
        return ACADEMY_TYPE_HUFF;
    }
#endif
        
    return -1;//协商返回-1
}

/************************************************
*根据学院BOSS活动ID获取学院类型
************************************************/
int CAcademyBossMgr::GetAcademyTypeByActID(short shActID)
{
    int iIndex = 0;

    iIndex = _stActList.FindAcademyAct(ACADEMY_TYPE_GRAN);
    CT_CHECK(iIndex, -1);
    CAcademyBossUnit& stActGran = _stActList.GetAcademyAct(iIndex);

    if (stActGran.GetActID() == shActID)
    {
        return ACADEMY_TYPE_GRAN;
    }

    iIndex = _stActList.FindAcademyAct(ACADEMY_TYPE_SLEN);
    CT_CHECK(iIndex, -1);
    CAcademyBossUnit& stActSlen = _stActList.GetAcademyAct(iIndex);

    if (stActSlen.GetActID() == shActID)
    {
        return ACADEMY_TYPE_SLEN;
    }
#if 0
    iIndex = _stActList.FindAcademyAct(ACADEMY_TYPE_RAVAN);
    CT_CHECK(iIndex, -1);
    CAcademyBossUnit& stActRavan = _stActList.GetAcademyAct(iIndex);

    if (stActRavan.GetActID() == shActID)
    {
        return ACADEMY_TYPE_RAVAN;
    }
        
    iIndex = _stActList.FindAcademyAct(ACADEMY_TYPE_HUFF);
    CT_CHECK(iIndex, -1);
    CAcademyBossUnit& stActHuff = _stActList.GetAcademyAct(iIndex);

    if (stActHuff.GetActID() == shActID)
    {
        return ACADEMY_TYPE_HUFF;
    }
#endif
    return -1;//协商返回-1
}

int CAcademyBossMgr::InitPlayerData(CPlayerCacheData& stPlayerCache,
        int iAcademyType)
{
    int iIndex = 0;
    int iBeginTime = 0;
    int iAttackAcademy = 0;
    bool bMerlin = false;
    bool bInspire = false;
    bool bRoleDead = false;
    bool bRoleCooling = false;

    iIndex = stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ROLE_EMPTY);

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    iBeginTime = CMainCtrl::m_pstMain->m_stActMgr.GetBeginTime(
        stActUnit.GetActID());

    if (iBeginTime > stAcademyRole.GetBeginTime())
    {
        stAcademyRole.Clear();

        stAcademyRole.SetEndTime(stAcademyMon.GetEndTime());
        stAcademyRole.SetBeginTime(iBeginTime);

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetDeadID());
        if (iIndex >= 0)
        {
            bRoleDead = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetDeadID(), false);
            AcademyBossNotify(stPlayerCache._uiGID, CMD_ACADEMY_BOSS_SUB_REVIVE,
                iAcademyType, true);
        }

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetMerlinID());
        if (iIndex >= 0)
        {
            bMerlin = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetMerlinID(), false);
        }

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetInspireID());
        if (iIndex >= 0)
        {
            bInspire = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetInspireID(), false);
        }

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetCoolingID());
        if (iIndex >= 0)
        {
            bRoleCooling = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetCoolingID(), false);
        }

        if (bMerlin || bInspire || bRoleDead || bRoleCooling)
        {
            if (CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetDeadID()) || 
                CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetMerlinID()) ||
                CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetInspireID()) ||
                CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetCoolingID()))
            {
                CMainCtrl::m_pstMain->m_stStatusMgr.NotifyUserStatusToSelfByGID(
                    stPlayerCache._uiGID);
            }
        }
    }

    return 0;
}

int CAcademyBossMgr::GetMerlinGold(CPlayerCacheData& stPlayerCache,
        int iAcademyType)
{
    int iGold = 0;
    int iIndex = 0;

    iIndex = stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ACADEMY_BOSS_MERLIN_GOLD_MAX);//返回金币数这里按最大返回

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    iGold = ACADEMY_BOSS_MERLIN_GOLD_INIT +
        (stAcademyRole.GetMerlinTimes() * ACADEMY_BOSS_MERLIN_GOLD_ADD);

    if (iGold > ACADEMY_BOSS_MERLIN_GOLD_MAX)
    {
        iGold = ACADEMY_BOSS_MERLIN_GOLD_MAX;
    }
    return iGold;
}

int CAcademyBossMgr::GetReviveGold(CPlayerCacheData& stPlayerCache,
        int iAcademyType)
{
    int iGold = 0;
    int iIndex = 0;

    iIndex = stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ACADEMY_BOSS_DEAD_GOLD_MAX);//返回金币数这里按最大返回

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    iGold = ACADEMY_BOSS_DEAD_GOLD_INIT +
        (stAcademyRole.GetDieTimes() * ACADEMY_BOSS_DEAD_GOLD_ADD);

    if (iGold > ACADEMY_BOSS_DEAD_GOLD_MAX)
    {
        iGold = ACADEMY_BOSS_DEAD_GOLD_MAX;
    }
    return iGold;
}

bool CAcademyBossMgr::IsValidAcademyType(int iAcademyType)
{
#if 0
    return (ACADEMY_TYPE_GRAN == iAcademyType ||
            ACADEMY_TYPE_SLEN == iAcademyType ||
            ACADEMY_TYPE_RAVAN == iAcademyType ||
            ACADEMY_TYPE_HUFF == iAcademyType);
#endif
    return (ACADEMY_TYPE_GRAN == iAcademyType ||
            ACADEMY_TYPE_SLEN == iAcademyType);
}

bool CAcademyBossMgr::IsValidMonsterType(int iMonsterType)
{
    return (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType ||
            ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType ||
            ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType);
}

//梅林祝福
int CAcademyBossMgr::BuyMerlin(CPlayerBaseInfo& stPlayerBase,
        CPlayerCacheData& stPlayerCache, MsgReqAcademyBoss& stReq,
        MsgAnsAcademyBoss& stAns)
{
    int iRet = 0;
    int iIndex = 0;
    int iAcademyType = stReq.academy_type();

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(stActUnit.GetActID()))
    {
        return ERROR_ACADEMY_BOSS_ACT_NO_OPEN;
    }

    //是否学院BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
            GetAcademyBossMapID(iAcademyType), stPlayerBase._uiGID))
    {
        return ERROR_ACADEMY_BOSS_NOT_IN_MAP;
    }

    //角色状态是否已满
    if (stPlayerCache._stUserStatus.IsUserStatusFull())
    {
        return ERROR_STATUS_UNIT_FULL;
    }

    iRet = InitPlayerData(stPlayerCache, iAcademyType);
    CT_RETURN(iRet);

    //检查状态配置
    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
        stActStatusCfg.GetMerlinID());
    CT_CHECK(iIndex, ERROR_STATUS_EMPTY_CFG);

    CStatusCfgData& stStatusCfg =
        CMainCtrl::m_pstMain->m_stStatusMgr.GetStatusCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetMerlinID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        if (stStatusCfg.GetAddMax() > 0 &&
            stStatusUnit.GetAddNum() >= stStatusCfg.GetAddMax())
        {
            return ERROR_STATUS_MAX_ADD_TIMES;
        }
    }

    iIndex =
        stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ROLE_EMPTY);

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    char chMerlinTimes = stAcademyRole.GetMerlinTimes();
    CT_CHECK(chMerlinTimes, ERROR_STATUS_DATA_IN_ROLE);

    int iGold = GetMerlinGold(stPlayerCache, iAcademyType);

    //是否金币足够
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBase,
        OSS_MONEY_MODULE_32, iGold);
    CT_RETURN(iRet);

    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBase._uiGID,
        NOTIFY_USER_MONEY);

    iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(stPlayerCache,
        stActStatusCfg.GetMerlinID(), stAcademyRole.GetEndTime(),
        stActUnit.GetActID(), true);
    CT_RETURN(iRet);

    stAcademyRole.SetMerlinTimes(chMerlinTimes + 1);

    MsgAcademyBossRole* pstBossRole = stAns.mutable_role_info();
    if (!pstBossRole) {CT_WARNING(("boss role pointer null"));return -1;}

    pstBossRole->set_merlin_gold(GetMerlinGold(stPlayerCache, iAcademyType));

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetMerlinID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                    stPlayerCache, iIndex);

        pstBossRole->set_merlin_remain(
            stStatusCfg.GetAddMax() - stStatusUnit.GetAddNum());
    }

    return 0;
}

//鼓舞状态
int CAcademyBossMgr::AddInspire(CPlayerCacheData& stPlayerCache,
        int iAcademyType, int iAddNum)
{
    int iRet = 0;
    int iIndex = 0;

    if (iAddNum <= 0)
    {
        CT_WARNING(("role(%u) add inspire but add num(%d) error",
            stPlayerCache._uiGID,iAddNum));
        return 0;
    }

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(stActUnit.GetActID()))
    {
        return ERROR_ACADEMY_BOSS_ACT_NO_OPEN;
    }

    //是否学院BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
            GetAcademyBossMapID(iAcademyType), stPlayerCache._uiGID))
    {
        return ERROR_ACADEMY_BOSS_NOT_IN_MAP;
    }

    //角色状态是否已满
    if (stPlayerCache._stUserStatus.IsUserStatusFull())
    {
        return ERROR_STATUS_UNIT_FULL;
    }

    iRet = InitPlayerData(stPlayerCache, iAcademyType);
    CT_RETURN(iRet);

    //检查状态配置
    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
        stActStatusCfg.GetInspireID());
    CT_CHECK(iIndex, ERROR_STATUS_EMPTY_CFG);

    CStatusCfgData& stStatusCfg =
        CMainCtrl::m_pstMain->m_stStatusMgr.GetStatusCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetInspireID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        if (stStatusCfg.GetAddMax() > 0 &&
            stStatusUnit.GetAddNum() >= stStatusCfg.GetAddMax())
        {
            return ERROR_STATUS_MAX_ADD_TIMES;
        }
    }

    iIndex = stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ROLE_EMPTY);

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    for (int i = 0; i < iAddNum; ++i)
    {
        iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
            stPlayerCache, stActStatusCfg.GetInspireID(),
            stAcademyRole.GetEndTime(), stActUnit.GetActID(), false);
        CT_RETURN(iRet);
    }
    if (iAddNum > 0 && CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
            stActStatusCfg.GetInspireID()))
    {
        CMainCtrl::m_pstMain->m_stStatusMgr.NotifyUserStatusToSelfByGID(
            stPlayerCache._uiGID);
    }

    return 0;
}

//金币复活
int CAcademyBossMgr::DeadRevive(CPlayerBaseInfo& stPlayerBase,
        CPlayerCacheData& stPlayerCache, MsgReqAcademyBoss& stReq,
        MsgAnsAcademyBoss& stAns)
{
    int iRet = 0;
    int iIndex = 0;
    int iAcademyType = stReq.academy_type();
    int iAttackAcademy = 0;

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    //活动已结束 不能使用此流程清除死亡状态
    if (stAcademyMon.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
    {
        return ERROR_ACADEMY_BOSS_ALREADY_END;
    }

    //是否学院BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
            GetAcademyBossMapID(iAcademyType), stPlayerBase._uiGID))
    {
        return ERROR_ACADEMY_BOSS_NOT_IN_MAP;
    }

    iRet = InitPlayerData(stPlayerCache, iAcademyType);
    CT_RETURN(iRet);

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //处理死亡状态
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetDeadID());
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_NOT_IN_DEAD);

    CStatusUnit& stStatusUnit =
        CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(stPlayerCache, iIndex);

    //死亡状态到期 不扣金子 主动清除
    if (stStatusUnit.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
    {
        CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
            stActStatusCfg.GetDeadID(), true);
        AcademyBossNotify(stPlayerBase._uiGID, CMD_ACADEMY_BOSS_SUB_REVIVE,
            iAcademyType, true);
        return ERROR_STATUS_END_NO_EXPEND;
    }

    iIndex =
        stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ROLE_EMPTY);

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    char chDieTimes = stAcademyRole.GetDieTimes();
    if (chDieTimes < 0)
    {
        CT_WARNING(("role(%u) die times error(DieTimes=%d)",
                    stPlayerBase._uiGID,chDieTimes));
        chDieTimes = 0;
    }

    int iGold = GetReviveGold(stPlayerCache, iAcademyType);

    //是否金币足够
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBase,
        OSS_MONEY_MODULE_33, iGold);
    CT_RETURN(iRet);

    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBase._uiGID,
        NOTIFY_USER_MONEY);

    //释放死亡状态
    CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
        stActStatusCfg.GetDeadID(), true);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetCoolingID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        //战斗冷却没有叠加层数 直接修改到期时间
        stStatusUnit.SetEndTime(0);
    }

    stAcademyRole.SetDieTimes(chDieTimes + 1);

    MsgAcademyBossRole* pstBossRole = stAns.mutable_role_info();
    if (!pstBossRole) {CT_WARNING(("boss role pointer null"));return -1;}

    pstBossRole->set_revive_gold(GetReviveGold(stPlayerCache, iAcademyType));

    AcademyBossNotify(stPlayerBase._uiGID, CMD_ACADEMY_BOSS_SUB_REVIVE,
        iAcademyType, false);

    return 0;
}

int CAcademyBossMgr::GetMonsterHP(CAcademyBossMonster& stAcademyMon,
        int iMonsterType)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        return stAcademyMon.GetLeftMonHP();
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
        return stAcademyMon.GetRightMonHP();
    }
    else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
        return stAcademyMon.GetBossMonHP();
    }

    return 0;
}

int CAcademyBossMgr::SetMonsterHP(CAcademyBossMonster& stAcademyMon,
        int iMonsterType, int iHP)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        stAcademyMon.SetLeftMonHP(iHP);
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
        stAcademyMon.SetRightMonHP(iHP);
    }
    else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
        stAcademyMon.SetBossMonHP(iHP);
    }

    return 0;
}

MsgAcademyBossMonster& CAcademyBossMgr::GetMsgMonRole(
        CAcademyBossMonster& stAcademyMon, int iMonsterType)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        return stAcademyMon.GetMsgLeftRole();
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
        return stAcademyMon.GetMsgRightRole();
    }

    return stAcademyMon.GetMsgBossRole();
}

CPlayerEquip& CAcademyBossMgr::GetMonRoleEquip(
        CAcademyBossMonster& stAcademyMon, int iMonsterType)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        return stAcademyMon.GetLeftRoleEquip();
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
        return stAcademyMon.GetRightRoleEquip();
    }

    return stAcademyMon.GetBossRoleEquip();
}

int CAcademyBossMgr::GetMonsterHPMax(CAcademyBossMonster& stAcademyMon,
        int iMonsterType)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        return stAcademyMon.GetLeftMonHPMax();
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
        return stAcademyMon.GetRightMonHPMax();
    }
    else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
        return stAcademyMon.GetBossMonHPMax();
    }

    return 0;
}

int CAcademyBossMgr::GetAllMonsterHPMax(CAcademyBossMonster& stAcademyMon)
{
    return stAcademyMon.GetLeftMonHPMax() + stAcademyMon.GetRightMonHPMax() +
            stAcademyMon.GetBossMonHPMax();
}

unsigned int CAcademyBossMgr::GetMonsterID(CAcademyBossMonster& stAcademyMon,
        int iMonsterType)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        return stAcademyMon.GetLeftMonsterID();
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
       return  stAcademyMon.GetRightMonsterID();
    }
    else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
       return  stAcademyMon.GetBossMonsterID();
    }

    return 0;
}

unsigned int CAcademyBossMgr::GetMonGroupID(CAcademyBossMonster& stAcademyMon,
        int iMonsterType)
{
    if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType)
    {
        return stAcademyMon.GetLeftMonGroupID();
    }
    else if (ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
    {
       return  stAcademyMon.GetRightMonGroupID();
    }
    else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
       return  stAcademyMon.GetBossMonGroupID();
    }

    return 0;
}

//进入战斗
int CAcademyBossMgr::BossBattle(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerCacheData& stPlayerCache, MsgReqAcademyBoss& stReq,
        MsgAnsAcademyBoss& stAns, CAcademyBossCmdData& stCmdData)
{
    int iRet = 0;
    int iIndex = 0;
    int iMonsterType = stReq.monster_type();
    int iAcademyType = stReq.academy_type();
    int iAttackAcademy = 0;

    _bKill = false;
    _bFifty = false;
    _bFootboyKill = false;
    bool bSceneNotify = false;
    SetInspireNum(0);

    if (!IsValidMonsterType(iMonsterType))
    {
        return ERROR_ACADEMY_BOSS_MONSTER_TYPE;
    }

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(stActUnit.GetActID()))
    {
        return ERROR_ACADEMY_BOSS_ACT_NO_OPEN;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    if (CMainCtrl::m_pstMain->m_iNow < stAcademyMon.GetMonBornTime())
    {
        return ERROR_ACADEMY_BOSS_ACT_NO_OPEN;
    }

    //是否学院BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
            GetAcademyBossMapID(iAcademyType), stPlayerBase._uiGID))
    {
        return ERROR_ACADEMY_BOSS_NOT_IN_MAP;
    }

    //是否BOSS已死亡
    int iMonsterHP = GetMonsterHP(stAcademyMon, iMonsterType);
    if (iMonsterHP <= 0)
    {
        return ERROR_ACADEMY_BOSS_ALREADY_DEAD;
    }

    //要求先击杀左右侍从 才能攻击试练使者
    if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
        if (GetMonsterHP(stAcademyMon, ENUM_ACADEMY_BOSS_MON_LEFT) > 0 ||
            GetMonsterHP(stAcademyMon, ENUM_ACADEMY_BOSS_MON_RIGHT) > 0)
        {
            return ERROR_ACADEMY_BOSS_ATTACK_LAST;
        }
    }

    iRet = InitPlayerData(stPlayerCache, iAcademyType);
    CT_RETURN(iRet);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_EMPTY_CFG);

    CActCfgData& stActCfgData =
        CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //战斗冷却
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetCoolingID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        //战斗等待状态到期 先不主动清除 只判断时间
        if (stStatusUnit.GetEndTime() > CMainCtrl::m_pstMain->m_iNow)
        {
            return ERROR_STATUS_IN_FIGHT_CD;
        }
    }

    //是否死亡
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetDeadID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        //死亡状态到期 不扣金子 主动清除
        if (stStatusUnit.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
        {
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetDeadID(), true);
        }
        else
        {
            return ERROR_ACADEMY_BOSS_ROLE_IN_DEAD;
        }
    }

    CMonsterGroupConfigData stMonsterGroup;
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(
        GetMonGroupID(stAcademyMon, iMonsterType),
        stAcademyMon.GetWorldLevel(), stMonsterGroup);
    CT_RETURN(iRet);

    MsgBattleResult* pstBattleResult = stAns.mutable_battle_result();
    if (!pstBattleResult)
    {
        return RET_SYS_NULL_POINTER;
    }

    SetAcademyType(iAcademyType);
    SetMonsterType(iMonsterType);

    iRet = CMainCtrl::m_pstMain->m_stBattleMgr.DealWorldBoss(stPlayerBase,
        stPlayerDetail, stPlayerOnline, stMonsterGroup, *pstBattleResult,
        stActCfgData.GetType());
    CT_RETURN(iRet);

	if (stReq.has_battle_ext_info())
	{
		(*pstBattleResult->mutable_battle_ext_info()) =
            stReq.battle_ext_info();
	}

    for (int i = 0; i <
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount(); ++i)
    {
        CBattleRole& stBattleObj =
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(i);
        if (stBattleObj.IsMonsterObject())
        {
            stAcademyMon.AddAtkValue(
                GetMonsterHP(stAcademyMon, iMonsterType) - stBattleObj.GetHP());
            break;
        }
    }

    iIndex =
        stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ROLE_EMPTY);

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    //累加角色攻击伤害
    stAcademyRole.AddAtkValue(stAcademyMon.GetAtkValue());

    if (stAcademyMon.GetAtkValue() > 0)
    {
        CMainCtrl::m_pstMain->m_stRewardBackMgr.SetPlayerAct(
            stPlayerBase._uiGID, ACT_ID_GRAN_BOSS);
    }

    //更新排名榜
    if (stAcademyMon.GetAtkValue() > 0 && stAcademyRole.GetAtkValue() > 0)
    {
        CAcademyBossAtkUnit stRankUnit;
        int iOldOrder = -1;
        int iNewOrder = -1;
        stRankUnit.SetGID(stPlayerCache._uiGID);
        stRankUnit.SetRoleName(stPlayerBase._sRoleName());
        stRankUnit.SetAcademy(stPlayerBase._ucAcademy);
        stRankUnit.SetAtkValue(stAcademyRole.GetAtkValue());
        stAcademyMon.UpdateRank(stRankUnit, iOldOrder, iNewOrder);

        if ((iNewOrder >= 0 &&
             iNewOrder < CAcademyBossMonster::AB_MONSTER_ATK_RANK_COUNT) ||
            (iNewOrder >= 0 && iOldOrder != iNewOrder))
        {
            bSceneNotify = true;
        }
    }

    for (int i = 0; i <
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount(); ++i)
    {
        //先处理Boss怪物 如果怪物死亡 活动结束 不需要加主角死亡惩罚
        CBattleRole& stBattleObj =
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(i);
        if (stBattleObj.IsMonsterObject())
        {
            iRet = DealMonsterAfterBattle(stBattleObj, stPlayerCache._uiGID,
                iAcademyType, iMonsterType, stCmdData);
            if (iRet){CT_ERROR(("Deal monster after battle error(%d)!",iRet));}
            break;
        }
    }

    for (int i = 0; i <
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount(); ++i)
    {
        //处理主角
        CBattleRole& stBattleObj =
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(i);
        if (stBattleObj.IsPlayerObject())
        {
            iRet = DealPlayerAfterBattle(stPlayerOnline, stPlayerCache, stAns,
                pstBattleResult->result(), iAcademyType, iMonsterType,
                stCmdData);
            if (iRet){CT_ERROR(("Deal player after battle error(%d)!",iRet));}

            break;
        }
    }

    //拼装全服提示走马灯数据
    AcademyBossNotifyTip(stPlayerBase, iAcademyType, iMonsterType, stCmdData);

    if (bSceneNotify)
    {
        AcademyBossNotify(iAcademyType);
    }

    return 0;
}

//修正战斗开始前数据 修正血量以及组装骑乘信息
int CAcademyBossMgr::ReviseBeforeBattle(int iBossBattleID)
{
    if (iBossBattleID < 0 ||
        iBossBattleID >=
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount())
    {
        return ERROR_BATTLE_GRID_ID;
    }

    int iRet = 0;
    int iIndex = 0;
    int iAcademyType = GetAcademyType();
    int iMonsterType = GetMonsterType();
    int iAttackAcademy = 0;

    if (!IsValidMonsterType(iMonsterType))
    {
        return ERROR_ACADEMY_BOSS_MONSTER_TYPE;
    }

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    stAcademyMon.SetAtkValue(0);

    CBattleRole& stBattleRole =
        CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(iBossBattleID);

    stBattleRole.SetHP(GetMonsterHP(stAcademyMon, iMonsterType));

    MsgAcademyBossMonster& stMsgAcademyMon = GetMsgMonRole(stAcademyMon,
        iMonsterType);

    CBattleRoleData& stBattleRoleData = stBattleRole.GetRoleBase();
    const MsgRoleInfo& stMsgRoleInfo = stMsgAcademyMon.role_info();

    //组装显示名称 一
    if (ACADEMY_TYPE_GRAN == iAttackAcademy)
    {
        if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType ||
            ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("格兰学院试炼侍从");
        }
        else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("格兰学院试炼使者");
        }
    }
    else if (ACADEMY_TYPE_SLEN == iAttackAcademy)
    {
        if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType ||
            ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("斯林学院试炼侍从");
        }
        else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("斯林学院试炼使者");
        }
    }
    else if (ACADEMY_TYPE_RAVAN == iAttackAcademy)
    {
        if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType ||
            ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("拉文学院试炼侍从");
        }
        else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("拉文学院试炼使者");
        }
    }
    else if (ACADEMY_TYPE_HUFF == iAttackAcademy)
    {
        if (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType ||
            ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("霍奇学院试炼侍从");
        }
        else if (ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
        {
            stBattleRoleData._sObjName.Set("霍奇学院试炼使者");
        }
    }

    if (!stMsgAcademyMon.has_role_info())
    {
        CT_TRACE(("academy(%d) monster(%d) has not been initialized!",
                    iAcademyType,iMonsterType));
        return 0;//如果学院竞技榜没有取到 这里有可能为空
    }
    
    const MsgObjBase& stMsgObjBase = stMsgRoleInfo.base_info();

    stBattleRoleData._chType = GAME_OBJ_TYPE_SERVER_MONSTER_FRONT_ROLE;
    //stBattleRoleData._uiObjID;//暂时不修改 还是怪物的配置ID
    stBattleRoleData._ucCareer = stMsgObjBase.career();
    stBattleRoleData._bIsMale = stMsgObjBase.sex();
    stBattleRoleData._shLevel = stMsgObjBase.level();

    unsigned short usEquipCfgID = 0;
    stBattleRoleData._stEquip.Clear();
    CPlayerEquip& stPlayerEquip = GetMonRoleEquip(stAcademyMon, iMonsterType);
    for (int i = 0; i < stPlayerEquip._auiPlayerEquip.Size(); ++i)
    {
        if (stPlayerEquip._auiPlayerEquip[i] > 0)
        {
            iRet = CMainCtrl::m_pstMain->m_stEquipMgr.GetConfigIdByEquipId(
                stPlayerEquip._auiPlayerEquip[i], usEquipCfgID);
            if (!iRet)
            {
                stBattleRoleData._stEquip.SetEquip(usEquipCfgID, i+1);
            }
        }
    }

    stBattleRoleData._uiMountID = GetMonsterID(stAcademyMon, iMonsterType);

    //组装显示名称 二
    stBattleRoleData._sObjName.Cat("@%s",stMsgRoleInfo.name().c_str());
                
    return 0;
}

int CAcademyBossMgr::DealMonsterAfterBattle(CBattleRole& stBattleObj,
        unsigned int uiGID, int iAcademyType, int iMonsterType,
        CAcademyBossCmdData& stCmdData)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    if (!IsValidMonsterType(iMonsterType))
    {
        return ERROR_ACADEMY_BOSS_MONSTER_TYPE;
    }

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    //战斗前血量
    int iMonsterHPOld = GetMonsterHP(stAcademyMon, iMonsterType);
    //初始化血量
    int iMonsterHPMax = GetMonsterHPMax(stAcademyMon, iMonsterType);

    //血量更新
    SetMonsterHP(stAcademyMon, iMonsterType, stBattleObj.GetHP());

    //战斗后血量
    int iMonsterHPNew = GetMonsterHP(stAcademyMon, iMonsterType);

    if (stAcademyMon.GetBossBornTime() <= 0 &&
        GetMonsterHP(stAcademyMon, ENUM_ACADEMY_BOSS_MON_LEFT) <= 0 &&
        GetMonsterHP(stAcademyMon, ENUM_ACADEMY_BOSS_MON_RIGHT) <= 0)
    {
        stAcademyMon.SetBossBornTime(CMainCtrl::m_pstMain->m_iNow);
    }

    if (iMonsterHPNew > 0 && ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
#define ACADEMY_BOSS_INSPIRE_TRIGGER_RATE 200
        //学院BOSS的鼓舞状态只根据大BOSS的血量千分比临界施加
        int iTriggerAddNum = GetTriggerAddNum(iMonsterHPNew, iMonsterHPOld,
                iMonsterHPMax, ACADEMY_BOSS_INSPIRE_TRIGGER_RATE);
        SetInspireNum(iTriggerAddNum);
    }

    if (stAcademyMon.GetAtkValue() > 0 && iMonsterHPMax > 0 &&
            ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
        int64 i64RatioTmp = INT64_1 * iMonsterHPOld * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonsterHPMax;
        int iOldHPPec = (int)(i64RatioTmp);

        i64RatioTmp = INT64_1 * iMonsterHPNew * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonsterHPMax;
        int iNowHPPec = (int)(i64RatioTmp);

#define WORLD_BOSS_REWARD_PERCENT 500      //BOSS击杀奖励百分比

        if (iOldHPPec >= WORLD_BOSS_REWARD_PERCENT &&
            iNowHPPec < WORLD_BOSS_REWARD_PERCENT)
        {
            _bFifty = true;
        }
    }

    if (iMonsterHPNew <= 0 &&
        (ENUM_ACADEMY_BOSS_MON_LEFT == iMonsterType ||
         ENUM_ACADEMY_BOSS_MON_RIGHT == iMonsterType))
    {
        _bFootboyKill = true;
    }

    //活动处理
    if (iMonsterHPNew <= 0 && ENUM_ACADEMY_BOSS_MON_BOSS == iMonsterType)
    {
        _bKill = true;

        //设置学院BOSS关闭时间
        stAcademyMon.SetEndTime(CMainCtrl::m_pstMain->m_iNow);
        
        stCmdData.SetCloseActID(stActUnit.GetActID());
    }

    return 0;
}

//判断是否在某个区间返回横跨区间的叠加数
int CAcademyBossMgr::GetTriggerAddNum(int iValNow, int iValOld, int iValMax,
        int iRate)
{
    if (iValMax <= 0 || iValNow < 0 || iValNow >= iValOld || iValOld > iValMax
        || iRate <= 0 || iRate > MAX_BATTLE_DATA_PRECISION)
    {
        CT_ERROR(("iValNow(%d) iValOld(%d) iValMax(%d) iRate(%d)",iValNow,
            iValOld,iValMax,iRate));
        return 0;
    }

    //使用整数计算方法
    int64 i64RateTmp = INT64_1 * iValMax * iRate;
    i64RateTmp = i64RateTmp / MAX_BATTLE_DATA_PRECISION;
    int iRateVal = (int)(i64RateTmp);
    int iRateMax = MAX_BATTLE_DATA_PRECISION / iRate;
    int iRateTmp = 0;

    for (int i = 1; i <= iRateMax; ++i)
    {
        iRateTmp = iValMax - i * iRateVal;
        if (iValNow <= iRateTmp && iValOld > iRateTmp)
        {
            if (iValOld - iValNow <= iRateVal)
            {
                iRateTmp = 1;
            }
            else
            {
                iRateTmp = (iValOld - iValNow) / iRateVal;
            }
            CT_TRACE(("ValNow(%d) ValOld(%d) ValMax(%d) Rate(%d/%d) AddNum(%d)",
                iValNow,iValOld,iValMax,iRate,MAX_BATTLE_DATA_PRECISION,
                iRateTmp));
            return iRateTmp;
        }
    }

    return 0;
}

int CAcademyBossMgr::DealPlayerAfterBattle(CPlayerOnlineData& stPlayerOnline,
        CPlayerCacheData& stPlayerCache, MsgAnsAcademyBoss& stAns,
        int iBattleResult, int iAcademyType, int iMonsterType,
        CAcademyBossCmdData& stCmdData)
{
    int iRet = 0;
    int iIndex = 0;
    int iAttackAcademy = 0;

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACT_UN_EXIST);

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    //奖励结算
    AcademyBossRoleReward(stPlayerCache, stAns, iAcademyType, iMonsterType,
        stCmdData);

    //活动已经结束
    if (stCmdData.GetCloseActID() > 0)
    {
        return 0;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    //鼓舞状态
    CT_TRACE(("role(%u) world boss attack value(%d).",
              stPlayerCache._uiGID,stAcademyMon.GetAtkValue()));

    if (GetInspireNum() > 0)
    {
        //给本地图所有角色增加一层鼓舞状态
        CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
        CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
            GetAcademyBossMapID(iAcademyType), auiMapUserList);

        for (int i = 0; i < auiMapUserList.Size(); ++i)
        {
            iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(
                auiMapUserList[i]);
            if (iIndex >= 0)
            {
                CPlayerCacheData& stPlayerCache =
                  CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];
                iRet = AddInspire(stPlayerCache, iAcademyType, GetInspireNum());
                CT_TRACE(("Role(%u) add inspire status ret(%d).",
                          auiMapUserList[i],iRet));
            }
        }
    }

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    if (BATTLE_RESULT_WIN != iBattleResult)
    {
        stPlayerOnline._usMapPosX = -1;             
        stPlayerOnline._usMapPosY = -1;

        //死亡状态没有叠加层数 直接修改到期时间
        iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
            stPlayerCache, stActStatusCfg.GetDeadID(),
            CMainCtrl::m_pstMain->m_iNow + ACADEMY_BOSS_DEAD_WAIT_TIME,
            stActUnit.GetActID(), false);
        if (iRet) {CT_ERROR(("role add dead status error(%d)",iRet));}

        AcademyBossNotify(stPlayerCache._uiGID, CMD_ACADEMY_BOSS_SUB_DEAD,
            iAcademyType, true);

        //战斗冷却没有叠加层数 直接修改到期时间
        iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
            stPlayerCache, stActStatusCfg.GetCoolingID(),
            CMainCtrl::m_pstMain->m_iNow + ACADEMY_BOSS_FIGHT_WAIT_TIME,
            stActUnit.GetActID(), false);
        if (iRet) {CT_ERROR(("role add fight cool status error(%d)",iRet));}

        if (CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                stActStatusCfg.GetDeadID()) || 
            CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                stActStatusCfg.GetCoolingID()))
        {
            CMainCtrl::m_pstMain->m_stStatusMgr.NotifyUserStatusToSelfByGID(
                stPlayerCache._uiGID);
        }
    }

    MsgAnsAcademyBoss stMsgAnsAB;
    GetAcademyBossMonster(stMsgAnsAB, iAcademyType);//怪物血量
    GetAcademyBossAtkRank(stMsgAnsAB, iAcademyType);//伤害排名
    GetAcademyBossRole(stPlayerCache, stMsgAnsAB, iAcademyType);//角色信息
    AcademyBossNotify(stPlayerCache._uiGID, CMD_ACADEMY_BOSS_SUB_ATK_RANK,
        iAcademyType, stMsgAnsAB);

    stAcademyMon.SetLastNotifyGID(stPlayerCache._uiGID);

    unsigned int uiRoleGID = 0;

    for (int i = 0; i < stAcademyMon.GetRankSize() &&
           i < CAcademyBossMonster::AB_MONSTER_RANK_SHOW_COUNT; ++i)
    {
        CAcademyBossAtkUnit& stAtkUnit = stAcademyMon.GetRankUnit(i);
        uiRoleGID = stAtkUnit.GetGID();
        if (uiRoleGID == stPlayerCache._uiGID)
        {
            continue;
        }

        //是否学院BOSS场景
        if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
                GetAcademyBossMapID(iAcademyType), uiRoleGID))
        {
            continue;
        }

        iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(uiRoleGID);
        if (iIndex < 0)
        {
            CT_WARNING(("role(%u) in world boss rank but cache data empty!",
                        uiRoleGID));
            continue;
        }

        CPlayerCacheData& stPlayerCacheTmp =
            CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

        GetAcademyBossRole(stPlayerCacheTmp, stMsgAnsAB, iAcademyType);

        AcademyBossNotify(stPlayerCacheTmp._uiGID,
            CMD_ACADEMY_BOSS_SUB_ATK_RANK, iAcademyType, stMsgAnsAB);
    }

    return 0;
}

int CAcademyBossMgr::GMSetMonsterHP(short shActID, int iNewHP, int iMonsterType)
{
    int iIndex = 0;
    int iAcademyType = 0;
    int iAttackAcademy = 0;

    if (!IsValidMonsterType(iMonsterType))
    {
        return ERROR_ACADEMY_BOSS_MONSTER_TYPE;
    }

    iAcademyType = GetAcademyTypeByActID(shActID);
    CT_CHECK(iAcademyType, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    return SetMonsterHP(stAcademyMon, iMonsterType, iNewHP);
}

int CAcademyBossMgr::GMSetWorldLevel(short shActID, int iNewLevel)
{
    int iIndex = 0;
    int iAcademyType = 0;
    int iAttackAcademy = 0;

    iAcademyType = GetAcademyTypeByActID(shActID);
    CT_CHECK(iAcademyType, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    stAcademyMon.SetWorldLevel(iNewLevel);

    return 0;
}

void CAcademyBossMgr::GMGetAcademyBoss(int iAcademyType,
        CTSizeString<MAX_BATTLE_NAME_BUFF>& szNameStr)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if (iIndex < 0) {return;}
    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    if (iIndex < 0) {return;}
    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    if (iIndex < 0) {return;}

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    szNameStr.Cat("敌对学院:%d ",iAttackAcademy);
    szNameStr.Cat("结束时间:%d ",stAcademyMon.GetEndTime());
    szNameStr.Cat("世界等级:%d ",stAcademyMon.GetWorldLevel());
    szNameStr.Cat("场景ID:%u ",GetAcademyBossMapID(iAcademyType));
    szNameStr.Cat("活动ID:%d ",stActUnit.GetActID());
    szNameStr.Cat("死亡:%d ",stActStatusCfg.GetDeadID());
    szNameStr.Cat("冷却:%d ",stActStatusCfg.GetCoolingID());
    szNameStr.Cat("祝福:%d ",stActStatusCfg.GetMerlinID());
    szNameStr.Cat("鼓舞:%d ",stActStatusCfg.GetInspireID());

    szNameStr.Cat("\n侍卫出生时间:%d ",stAcademyMon.GetMonBornTime());
    szNameStr.Cat("左侍卫(%u):%d/%d 右侍卫(%u):%d/%d ",
        stAcademyMon.GetLeftMonGroupID(),stAcademyMon.GetLeftMonHP(),
        stAcademyMon.GetLeftMonHPMax(),stAcademyMon.GetRightMonGroupID(),
        stAcademyMon.GetRightMonHP(),stAcademyMon.GetRightMonHPMax());
    szNameStr.Cat("\nBOSS出生时间:%d BOSS(%u):%d/%d",
        stAcademyMon.GetBossBornTime(),stAcademyMon.GetBossMonGroupID(),
        stAcademyMon.GetBossMonHP(),stAcademyMon.GetBossMonHPMax());

    szNameStr.Cat("\n学院BOSS排行榜总数:%d ",stAcademyMon.GetRankSize());

    for (int i = 0; i < stAcademyMon.GetRankSize(); ++i)
    {
        CAcademyBossAtkUnit& stRankUnit = stAcademyMon.GetRankUnit(i);

        szNameStr.Cat("\nGID:%u ",stRankUnit.GetGID());
        szNameStr.Cat("%s ",stRankUnit.GetRoleName());
        szNameStr.Cat("学院:%d ",stRankUnit.GetAcademy());
        szNameStr.Cat("伤害:%d",stRankUnit.GetAtkValue());
    }
}

int CAcademyBossMgr::GMDealAcademyBoss(MsgReqGMPlayer& stReq,
        MsgAnsGMPlayer& stAns)
{
    CTSizeString<MAX_BATTLE_NAME_BUFF> szNameStr;
    switch (stReq.sub_type())
    {
    case ID_GM_PLAYER_SUB_GET_ACADEMY_BOSS_INFO:
        {
            szNameStr.Cat("{格兰学院} ");
            GMGetAcademyBoss(ACADEMY_TYPE_GRAN, szNameStr);

            szNameStr.Cat("\n{斯林学院} ");
            GMGetAcademyBoss(ACADEMY_TYPE_SLEN, szNameStr);

            szNameStr.Cat("\n{拉文学院} ");
            GMGetAcademyBoss(ACADEMY_TYPE_RAVAN, szNameStr);

            szNameStr.Cat("\n{霍奇学院} ");
            GMGetAcademyBoss(ACADEMY_TYPE_HUFF, szNameStr);

            stAns.set_name(szNameStr.Get());
        }
        break;
    default:
        return ERROR_MAIN_SUB_CMD;
    }

    return 0;
}

void CAcademyBossMgr::AcademyBossNotify(int iAcademyType)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    if (!IsValidAcademyType(iAcademyType))
    {
        return;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    if (iIndex < 0) {return;}

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if (iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if (iIndex < 0) {return;}

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    if (CMainCtrl::m_pstMain->m_iNow < stAcademyMon.GetLastNotify())
    {
        return;
    }

    //活动已经结束
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(stActUnit.GetActID()))
    {
        return;
    }

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
        GetAcademyBossMapID(iAcademyType), auiMapUserList);
    if (auiMapUserList.Size() <= 0)
    {
        return;
    }

    MsgAnsAcademyBoss stMsgAnsAB;
    GetAcademyBossMonster(stMsgAnsAB, iAcademyType);//怪物血量
    GetAcademyBossAtkRank(stMsgAnsAB, iAcademyType);//伤害排名

    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(auiMapUserList[i]);
        if (iIndex < 0)
        {
            CT_WARNING(("Role(%u) in world boss map(%d) but cache data empty!",
                        auiMapUserList[i],GetAcademyBossMapID(iAcademyType)));
            continue;
        }

        CPlayerCacheData& stPlayerCache =
            CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

        iIndex = stAcademyMon.GetRankRoleOrder(auiMapUserList[i]);
        if (iIndex >= 0 &&
            iIndex < CAcademyBossMonster::AB_MONSTER_RANK_SHOW_COUNT)
        {
            continue;
        }

        if (stAcademyMon.GetLastNotifyGID() == auiMapUserList[i])
        {
            continue;
        }

        GetAcademyBossRole(stPlayerCache, stMsgAnsAB, iAcademyType);

        AcademyBossNotify(stPlayerCache._uiGID, CMD_ACADEMY_BOSS_SUB_ATK_RANK,
            iAcademyType, stMsgAnsAB);
    }

    stAcademyMon.SetLastNotify(CMainCtrl::m_pstMain->m_iNow +
        ACADEMY_BOSS_NOTIFY_WAIT_TIME);
}

void CAcademyBossMgr::AcademyBossNotify(unsigned int uiGID, int iSubCmd,
        int iAcademyType, bool bNotifySelf)
{
    int iIndex = 0;
    int iExpTime = 0;
    int iStatusID = 0;
    int iAttackAcademy = 0;

    MsgAnsAcademyBoss stAns;

    if (!IsValidAcademyType(iAcademyType))
    {
        return;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if (iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(uiGID);
    if (iIndex < 0)
    {
        CT_WARNING(("no cache data user(%u)",uiGID));
        return;
    }
	CPlayerCacheData& stPlayerCache =
        CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    if (iIndex < 0) {return;}

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    if (iIndex < 0) {return;}

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //注意都需要同步给同场景内的其他角色
    switch (iSubCmd)
    {
#if 0 //状态图标只需要提示给自己 有响应包返回 暂不需要下发其他角色
    case CMD_ACADEMY_BOSS_SUB_BUFF://购买梅林的祝福状态
        {
            iStatusID = stActStatusCfg.GetMerlinID();
        }
        break;
    case CMD_ACADEMY_BOSS_SUB_INSPIRE://施加鼓舞状态
        {
            iStatusID = stActStatusCfg.GetInspireID();
        }
        break;
#endif
    case CMD_ACADEMY_BOSS_SUB_REVIVE://金币复活
        break;
    case CMD_ACADEMY_BOSS_SUB_DEAD://角色死亡
        {
            iStatusID = stActStatusCfg.GetDeadID();
        }
        break;
    default:
        return;
    }

    if (iStatusID > 0)
    {
        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, iStatusID);
        if (iIndex < 0)
        {
            CT_WARNING(("role(%u) doesn't have status(%d)",stPlayerCache._uiGID,
                        iStatusID));
            return;
        }

        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(stPlayerCache,iIndex);

        iExpTime = stStatusUnit.GetEndTime();
    }

    stAns.set_sub_type(iSubCmd);
    stAns.set_attack_academy(iAttackAcademy);
    stAns.set_gid((int)uiGID);
    stAns.set_expire_time(iExpTime);

    PBMsgHead stMsgHead;
    stMsgHead.set_version(0);
    stMsgHead.set_time(CMainCtrl::m_pstMain->m_iNow);
    stMsgHead.set_msgact(0);
    stMsgHead.set_msgid(ID_MAIN_ACADEMY_BOSS);
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead,
        CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns,
        CMainCtrl::m_pstMain->m_stEncodeBuf);

    if (bNotifySelf)
    {
        CMainCtrl::m_pstMain->NotifyOnlineUser(uiGID,
            CMainCtrl::m_pstMain->m_stEncodeBuf);
    }

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
        GetAcademyBossMapID(iAcademyType), auiMapUserList);

    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        if (auiMapUserList[i] != uiGID)
        {
            CMainCtrl::m_pstMain->NotifyOnlineUser(auiMapUserList[i],
                CMainCtrl::m_pstMain->m_stEncodeBuf);
        }
    }
}

void CAcademyBossMgr::AcademyBossNotify(unsigned int uiGID, int iSubCmd,
        int iAcademyType, MsgAnsAcademyBoss& stAns)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if (iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    switch (iSubCmd)
    {
    case CMD_ACADEMY_BOSS_SUB_DEAD://角色死亡
        {
            CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
            CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
                GetAcademyBossMapID(iAcademyType), auiMapUserList);
            
            stAns.set_sub_type(iSubCmd);
            stAns.set_attack_academy(iAttackAcademy);
            stAns.set_gid((int)uiGID);
            for (int i = 0; i < auiMapUserList.Size(); ++i)
            {
                CMainCtrl::m_pstMain->NotifyOnlineUser(auiMapUserList[i],
                    ID_MAIN_ACADEMY_BOSS, stAns, false);
            }
        }
        break;
    case CMD_ACADEMY_BOSS_SUB_ATK_RANK://怪物血量+攻击伤害榜+主角名次及攻击伤害
        {
            stAns.set_attack_academy(iAttackAcademy);
            stAns.set_gid((int)uiGID);
            stAns.set_sub_type(iSubCmd);
            CMainCtrl::m_pstMain->NotifyOnlineUser(uiGID,
                ID_MAIN_ACADEMY_BOSS, stAns, false);
        }
        break;
    default:
        break;
    }
}

bool CAcademyBossMgr::IsFirstKillBoss(int iAttackAcademy)
{
    int iIndex = 0;
    int iAttackAcademyIndex = 0;

    if (!IsValidAcademyType(iAttackAcademy))
    {
        return false;
    }

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if (iIndex < 0)
    {
        return false;
    }

    iAttackAcademyIndex = iIndex;

    for (int i = 0; i < _stMonList.GetAcademyMonSize(); ++i)
    {
        if (i == iAttackAcademyIndex)
        {
            continue;
        }

        CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(i);
        if (stAcademyMon.GetBossMonHP() <= 0)
        {
            return false;
        }
    }

    return true;
}

void CAcademyBossMgr::AcademyBossNotifyTip(CPlayerBaseInfo& stPlayerBase,
        int iAcademyType, int iMonsterType, CAcademyBossCmdData& stCmdData)
{
    int iIndex = 0;
    int iMyAcademy = stPlayerBase._ucAcademy;
    int iAttackAcademy = 0;
    CTSizeString<ROLENAME_LEN> szNameStr;

    if (!IsValidMonsterType(iMonsterType))
    {
        return;
    }
    
    if (!IsValidAcademyType(iAcademyType))
    {
        return;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if (iIndex < 0) { return; }

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if (iIndex < 0) { return; }

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    MsgAcademyBossMonster& stMsgAcademyMon = GetMsgMonRole(stAcademyMon,
        iMonsterType);
    const MsgRoleInfo& stMsgRoleInfo = stMsgAcademyMon.role_info();

    if (_bFootboyKill && iMyAcademy == iAcademyType)
    //本学院玩家击杀本学院敌对侍从
    {
        MsgTips& stTips = stCmdData.GetFootboySelfTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_FOOTBOY_KILL_SELF);
        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }

        szNameStr.Set("%d",stCmdData.GetFootboySilver());//银币数量
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",stCmdData.GetFootboyReputation());//声望数量
        stTips.add_tip_argument(szNameStr());
    }
    else if (_bFootboyKill && iMyAcademy != iAcademyType)
    //玩家击杀非本学院敌对侍从
    {
        MsgTips& stTips = stCmdData.GetFootboyOtherTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_FOOTBOY_KILL_OTHER);
        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iAcademyType);//场景学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }

        szNameStr.Set("%d",stCmdData.GetFootboySilver());//银币数量
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",stCmdData.GetFootboyReputation());//声望数量
        stTips.add_tip_argument(szNameStr());
    }

    if (_bFifty && iMyAcademy == iAcademyType)
    //本学院玩家击杀本学院敌对BOSS50%伤害
    {
        MsgTips& stTips = stCmdData.GetFiftySelfTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_BOSS_FIFTY_SELF);
        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }

        szNameStr.Set("%d",stCmdData.GetFiftySilver());//银币数量
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",stCmdData.GetFiftyReputation());//声望数量
        stTips.add_tip_argument(szNameStr());
    }
    else if (_bFifty && iMyAcademy != iAcademyType)
    //玩家击杀非本学院敌对BOSS50%伤害
    {
        MsgTips& stTips = stCmdData.GetFiftyOtherTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_BOSS_FIFTY_OTHER);
        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iAcademyType);//场景学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }

        szNameStr.Set("%d",stCmdData.GetFiftySilver());//银币数量
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",stCmdData.GetFiftyReputation());//声望数量
        stTips.add_tip_argument(szNameStr());
    }

    if (_bKill && iMyAcademy == iAcademyType)
    //本学院玩家击杀本学院敌对BOSS
    {
        MsgTips& stTips = stCmdData.GetKillSelfTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_BOSS_KILL_SELF);
        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }

        szNameStr.Set("%d",stCmdData.GetKillSilver());//银币数量
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",stCmdData.GetKillReputation());//声望数量
        stTips.add_tip_argument(szNameStr());
    }
    else if (_bKill && iMyAcademy != iAcademyType)
    //玩家击杀非本学院敌对BOSS
    {
        MsgTips& stTips = stCmdData.GetKillOtherTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_BOSS_KILL_OTHER);
        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iAcademyType);//场景学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }

        szNameStr.Set("%d",stCmdData.GetKillSilver());//银币数量
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",stCmdData.GetKillReputation());//声望数量
        stTips.add_tip_argument(szNameStr());
    }

    //判断是否率先击杀大BOSS
    if (_bKill && iMyAcademy == iAcademyType && IsFirstKillBoss(iAttackAcademy))
    //前者判断以便保证首先进入本学院场景战斗 后者参数为敌对学院类型
    {
        MsgTips& stTips = stCmdData.GetKillFirstTips();
        stTips.Clear();
        stTips.set_type(TIPS_ACADEMY_BOSS_KILL_FIRST);
        stTips.add_tip_argument(stPlayerBase._sRoleName());//玩家昵称

        szNameStr.Set("%d",iMyAcademy);//所属学院
        stTips.add_tip_argument(szNameStr());

        szNameStr.Set("%d",iAttackAcademy);//敌对学院
        stTips.add_tip_argument(szNameStr());

        if (stMsgAcademyMon.has_role_info())
        {
            stTips.add_tip_argument(stMsgRoleInfo.name().c_str());
        }
        else
        {
            stTips.add_tip_argument("");
        }
    }
}

void CAcademyBossMgr::AcademyBossSceneNotify(int iAcademyType)
{
    int iIndex = 0;

    //本地图所有角色死亡状态清除
    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
        GetAcademyBossMapID(iAcademyType), auiMapUserList);
    if (auiMapUserList.Size() <= 0)
    {
        return;
    }

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    if (iIndex < 0) {return;}

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    if (iIndex < 0) {return;}

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    MsgAnsAcademyBoss stMsgAnsAB;
    GetAcademyBossMonster(stMsgAnsAB, iAcademyType);//怪物血量
    GetAcademyBossAtkRank(stMsgAnsAB, iAcademyType);//伤害排名
    //GetAcademyBossKiller(stMsgAnsAB, iAcademyType);

    //下发场景内所有在线角色
    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(auiMapUserList[i]);
        if (iIndex >= 0)
        {
            CPlayerCacheData& stPlayerCache =
                CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

            iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
                stPlayerCache, stActStatusCfg.GetDeadID());
            if (iIndex >= 0) //清除死亡状态
            {
                CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                    stActStatusCfg.GetDeadID(), true);

                AcademyBossNotify(stPlayerCache._uiGID,
                    CMD_ACADEMY_BOSS_SUB_REVIVE, iAcademyType, true);

            }

            //下发排名榜
            GetAcademyBossRole(stPlayerCache, stMsgAnsAB, iAcademyType);

            AcademyBossNotify(stPlayerCache._uiGID,
                CMD_ACADEMY_BOSS_SUB_ATK_RANK, iAcademyType, stMsgAnsAB);
        }
        else
        {
            CT_WARNING(("Role(%u) in world boss map(%d) but cache data empty!",
                        auiMapUserList[i],GetAcademyBossMapID(iAcademyType)));
        }
    }
}

void CAcademyBossMgr::GetAcademyBossMonster(MsgAnsAcademyBoss& stAns,
        int iAcademyType)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if (iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    stAns.set_attack_academy(iAttackAcademy);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if (iIndex < 0) {return;}

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    MsgAcademyBossMonster* pstMsgLeftMon = stAns.mutable_left_monster();
    MsgAcademyBossMonster* pstMsgRightMon = stAns.mutable_right_monster();
    MsgAcademyBossMonster* pstMsgBossMon = stAns.mutable_boss_monster();
    if (!pstMsgLeftMon || !pstMsgRightMon || !pstMsgBossMon)
    {
        CT_WARNING(("MsgAcademyBossMonster pointer null!"));
        return;
    }

    pstMsgLeftMon->set_max_hp(stAcademyMon.GetLeftMonHPMax());
    pstMsgLeftMon->set_level(stAcademyMon.GetWorldLevel());
    pstMsgLeftMon->set_born_time(stAcademyMon.GetMonBornTime());
    pstMsgLeftMon->set_mon_group_id(stAcademyMon.GetLeftMonGroupID());

#define WORLD_BOSS_MONSTER_BLOCK_PER 200      //BOSS血量隐藏千分比
#define WORLD_BOSS_MONSTER_BLOCK_NUM 1        //BOSS血量隐藏时此固定值给前端

    int iMonHPNow = 0;
    int iMonHPMax = 0;
    int iHPPercent = 0;
    int64 i64RatioTmp = 0;

    //应策划要求当怪物血量下降到一定比例时返回固定值给前端
    iMonHPNow = stAcademyMon.GetLeftMonHP();
    iMonHPMax = stAcademyMon.GetLeftMonHPMax();
    pstMsgLeftMon->set_now_hp(iMonHPNow);
    if (iMonHPNow > 0 && iMonHPNow < iMonHPMax)
    {
        i64RatioTmp = INT64_1 * iMonHPNow * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonHPMax;
        iHPPercent = (int)(i64RatioTmp);

        if (iHPPercent <= WORLD_BOSS_MONSTER_BLOCK_PER)
        {
            pstMsgLeftMon->set_now_hp(WORLD_BOSS_MONSTER_BLOCK_NUM);
        }
    }

    pstMsgRightMon->set_max_hp(stAcademyMon.GetRightMonHPMax());
    pstMsgRightMon->set_level(stAcademyMon.GetWorldLevel());
    pstMsgRightMon->set_born_time(stAcademyMon.GetMonBornTime());
    pstMsgRightMon->set_mon_group_id(stAcademyMon.GetRightMonGroupID());

    iMonHPNow = stAcademyMon.GetRightMonHP();
    iMonHPMax = stAcademyMon.GetRightMonHPMax();
    pstMsgRightMon->set_now_hp(iMonHPNow);
    if (iMonHPNow > 0 && iMonHPNow < iMonHPMax)
    {
        i64RatioTmp = INT64_1 * iMonHPNow * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonHPMax;
        iHPPercent = (int)(i64RatioTmp);

        if (iHPPercent <= WORLD_BOSS_MONSTER_BLOCK_PER)
        {
            pstMsgRightMon->set_now_hp(WORLD_BOSS_MONSTER_BLOCK_NUM);
        }
    }

    pstMsgBossMon->set_max_hp(stAcademyMon.GetBossMonHPMax());
    pstMsgBossMon->set_level(stAcademyMon.GetWorldLevel());
    pstMsgBossMon->set_born_time(stAcademyMon.GetBossBornTime());
    pstMsgBossMon->set_mon_group_id(stAcademyMon.GetBossMonGroupID());

    iMonHPNow = stAcademyMon.GetBossMonHP();
    iMonHPMax = stAcademyMon.GetBossMonHPMax();
    pstMsgBossMon->set_now_hp(iMonHPNow);
    if (iMonHPNow > 0 && iMonHPNow < iMonHPMax)
    {
        i64RatioTmp = INT64_1 * iMonHPNow * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonHPMax;
        iHPPercent = (int)(i64RatioTmp);

        if (iHPPercent <= WORLD_BOSS_MONSTER_BLOCK_PER)
        {
            pstMsgBossMon->set_now_hp(WORLD_BOSS_MONSTER_BLOCK_NUM);
        }
    }

    GetAcademyBossMonRole(iAcademyType, ENUM_ACADEMY_BOSS_MON_LEFT,
        (*pstMsgLeftMon));
    GetAcademyBossMonRole(iAcademyType, ENUM_ACADEMY_BOSS_MON_RIGHT,
        (*pstMsgRightMon));
    GetAcademyBossMonRole(iAcademyType, ENUM_ACADEMY_BOSS_MON_BOSS,
        (*pstMsgBossMon));
}

void CAcademyBossMgr::GetAcademyBossMonRole(int iAcademyType, int iMonsterType,
        MsgAcademyBossMonster& stMsgMonster)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if (iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if (iIndex < 0) {return;}

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    MsgAcademyBossMonster& stMsgAcademyMon = GetMsgMonRole(stAcademyMon,
        iMonsterType);

    if (!stMsgAcademyMon.has_role_info())
    {
        CT_TRACE(("academy(%d) monster(%d) has not been initialized!",
                    iAcademyType,iMonsterType));
        return;
    }
    
    MsgRoleInfo* pstMsgRoleInfo = stMsgMonster.mutable_role_info();
    if (!pstMsgRoleInfo) {CT_WARNING(("role pointer null"));return;}

    *pstMsgRoleInfo = stMsgAcademyMon.role_info();
    *(stMsgMonster.mutable_equips()) = stMsgAcademyMon.equips();
}

void CAcademyBossMgr::GetAcademyBossRole(CPlayerCacheData& stPlayerCache,
        MsgAnsAcademyBoss& stAns, int iAcademyType)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    stAns.clear_expire_time();//此值专表示死亡到期时间

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if(iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if(iIndex < 0) {return;}

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    iIndex = stPlayerCache._stAcademyBossRoleList.FindAcademyRole(iAcademyType);
    if(iIndex < 0) {return;}

    CAcademyBossRole& stAcademyRole =
        stPlayerCache._stAcademyBossRoleList.GetAcademyRole(iIndex);

    iIndex = _stActList.FindAcademyAct(iAcademyType);
    if(iIndex < 0) {return;}

    CAcademyBossUnit& stActUnit = _stActList.GetAcademyAct(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        stActUnit.GetActID());
    if(iIndex < 0) {return;}

    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    stAns.set_gid((int)stPlayerCache._uiGID);
    stAns.set_attack_academy(iAttackAcademy);
    stAns.set_end_time(stAcademyMon.GetEndTime());

    //处理死亡状态
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetDeadID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);

        //死亡状态到期 主动清除
        if (stStatusUnit.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
        {
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetDeadID(), true);
        }
        else
        {
            stAns.set_expire_time(stStatusUnit.GetEndTime());
        }
    }

    MsgAcademyBossRole* pstBossRole = stAns.mutable_role_info();
    if (!pstBossRole) {CT_WARNING(("boss role pointer null"));return;}

    pstBossRole->set_merlin_gold(GetMerlinGold(stPlayerCache, iAcademyType));
    pstBossRole->set_revive_gold(GetReviveGold(stPlayerCache, iAcademyType));

    pstBossRole->set_rank_order(
        stAcademyMon.GetRankRoleOrder(stPlayerCache._uiGID) + 1);

    pstBossRole->set_attack_value(stAcademyRole.GetAtkValue());

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
        stActStatusCfg.GetMerlinID());
    if (iIndex >= 0)
    {
        CStatusCfgData& stStatusCfg =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatusCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetMerlinID());
        if (iIndex >= 0)
        {
            CStatusUnit& stStatusUnit =
                CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                    stPlayerCache, iIndex);
        
            pstBossRole->set_merlin_remain(
                stStatusCfg.GetAddMax() - stStatusUnit.GetAddNum());
        }
        else
        {
            pstBossRole->set_merlin_remain(stStatusCfg.GetAddMax());
        }
    }
}

void CAcademyBossMgr::GetAcademyBossAtkRank(MsgAnsAcademyBoss& stAns,
        int iAcademyType)
{
    int iIndex = 0;
    int iAttackAcademy = 0;

    stAns.clear_attack_rank();

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    if(iIndex < 0) {return;}

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    if(iIndex < 0) {return;}

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    for (int i = 0; i < stAcademyMon.GetRankSize() &&
            i < CAcademyBossMonster::AB_MONSTER_RANK_SHOW_COUNT; ++i)
    {
        CAcademyBossAtkUnit& stAtkUnit = stAcademyMon.GetRankUnit(i);
        MsgAcademyBossAtkRank* pstMsgAtkRank = stAns.add_attack_rank();
        if (pstMsgAtkRank)
        {
            stAtkUnit.GetAtkRankUnit(*pstMsgAtkRank);
        }
    }

    stAns.set_attack_academy(iAttackAcademy);
    stAns.set_end_time(stAcademyMon.GetEndTime());
}

int CAcademyBossMgr::GetAcademyBossSceneInfo(CPlayerCacheData& stPlayerCache,
        MsgAnsAcademyBoss& stAns, int iAcademyType)
{
    InitPlayerData(stPlayerCache, iAcademyType);
    GetAcademyBossRole(stPlayerCache, stAns, iAcademyType);
    GetAcademyBossMonster(stAns, iAcademyType);//怪物血量
    GetAcademyBossAtkRank(stAns, iAcademyType);//伤害排名
    return 0;
}

int CAcademyBossMgr::AcademyBossRewardItem(unsigned int uiGID, int iRepu,
        int iExp, int iContri, int iSilver, CDropItem& stDropItem)
{
    if (iRepu > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_REPUTATION, iRepu);
    }

    if (iExp > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_EXP, iExp);
    }

    if (iContri > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_CONTRIBUTION, iContri);
    }

    if (iSilver > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_SILVER, iSilver);
    }

    if (stDropItem.Size() > 0)
    {
        stDropItem.SetOssModule(OSS_MODULE_ADMBOSS);
        CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL, uiGID, stDropItem);
    }

    return 0;
}

int CAcademyBossMgr::AcademyBossRoleReward(CPlayerCacheData& stPlayerCache,
        MsgAnsAcademyBoss& stAns, int iAcademyType, int iMonsterType,
        CAcademyBossCmdData& stCmdData)
{
    int iIndex = 0;
    int iMonMaxHP = 0;
    int iAttackAcademy = 0;

    int iTotalExp = 0;
    int iTotalRepu = 0;
    int iTotalContri = 0;
    int iTotalSilver = 0;

    if (!IsValidMonsterType(iMonsterType))
    {
        return ERROR_ACADEMY_BOSS_MONSTER_TYPE;
    }

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    iMonMaxHP = GetAllMonsterHPMax(stAcademyMon);

    if (stAcademyMon.GetAtkValue() <= 0 || iMonMaxHP <= 0)
    {
        return 0;
    }

    int64 i64RatioTmp = INT64_1 * stAcademyMon.GetAtkValue() *
        BATTLE_RATE_SKILL_PERCENT;
    i64RatioTmp /= iMonMaxHP;
    int iAttackValue = (int)(i64RatioTmp);
    if (iAttackValue <= 0)
    {
        iAttackValue = 1;
    }

    iIndex = CMainCtrl::m_pstMain->m_stWorldBossMgr.FindAttackConfig(
        iAttackValue);
    if (iIndex < 0)
    {
        CT_WARNING(("boss attack hp(%d) max hp(%d) attack id(%d) but cfg empty",
                    stAcademyMon.GetAtkValue(),iMonMaxHP,iAttackValue));
        return 0;
    }

    CWorldBossCfgAttack& stAttackCfg =
        CMainCtrl::m_pstMain->m_stWorldBossMgr.GetAttackConfig(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stWorldBossMgr.FindRewardConfig(
        stAcademyMon.GetWorldLevel());
    if (iIndex < 0)
    {
        CT_WARNING(("academy boss world level(%d) cfg empty",
                    stAcademyMon.GetWorldLevel()));
        return 0;
    }
    CWorldBossCfgReward& stRewardCfg =
        CMainCtrl::m_pstMain->m_stWorldBossMgr.GetRewardConfig(iIndex);

    i64RatioTmp = INT64_1 * stAttackCfg.GetReputationBase() *
        stRewardCfg.GetAcademyReputation();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iReputation = (int)(i64RatioTmp);

    i64RatioTmp = INT64_1 * stAttackCfg.GetExpBase() *
        stRewardCfg.GetAcademyExp();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iBattleExp = (int)(i64RatioTmp);

    i64RatioTmp = INT64_1 * stAttackCfg.GetContribuBase() *
        stRewardCfg.GetAcademyContribu();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iContribu = (int)(i64RatioTmp);

    i64RatioTmp = INT64_1 * stAttackCfg.GetSilverBase() *
        stRewardCfg.GetAcademySilver();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iSilver = (int)(i64RatioTmp);

    iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
    iTotalRepu += iReputation > 0 ? iReputation : 0;
    iTotalContri += iContribu > 0 ? iContribu : 0;
    iTotalSilver += iSilver > 0 ? iSilver : 0;

    if (_bFootboyKill)
    {
        iReputation = stRewardCfg.GetAcademyFootboyReputation();
        iBattleExp = stRewardCfg.GetAcademyFootboyExp();
        iContribu = stRewardCfg.GetAcademyFootboyContribu();
        iSilver = stRewardCfg.GetAcademyFootboySilver();

        iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
        iTotalRepu += iReputation > 0 ? iReputation : 0;
        iTotalContri += iContribu > 0 ? iContribu : 0;
        iTotalSilver += iSilver > 0 ? iSilver : 0;

        stCmdData.SetFootboyReputation(iReputation > 0 ? iReputation : 0);
        stCmdData.SetFootboyExp(iBattleExp > 0 ? iBattleExp : 0);
        stCmdData.SetFootboyContribu(iContribu > 0 ? iContribu : 0);
        stCmdData.SetFootboySilver(iSilver > 0 ? iSilver : 0);
    }

    if (_bFifty)
    {
        iReputation = stRewardCfg.GetAcademyFiftyReputation();
        iBattleExp = stRewardCfg.GetAcademyFiftyExp();
        iContribu = stRewardCfg.GetAcademyFiftyContribu();
        iSilver = stRewardCfg.GetAcademyFiftySilver();

        iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
        iTotalRepu += iReputation > 0 ? iReputation : 0;
        iTotalContri += iContribu > 0 ? iContribu : 0;
        iTotalSilver += iSilver > 0 ? iSilver : 0;

        stCmdData.SetFiftyReputation(iReputation > 0 ? iReputation : 0);
        stCmdData.SetFiftyExp(iBattleExp > 0 ? iBattleExp : 0);
        stCmdData.SetFiftyContribu(iContribu > 0 ? iContribu : 0);
        stCmdData.SetFiftySilver(iSilver > 0 ? iSilver : 0);
    }

    if (_bKill)
    {
        iReputation = stRewardCfg.GetAcademyKillReputation();
        iBattleExp = stRewardCfg.GetAcademyKillExp();
        iContribu = stRewardCfg.GetAcademyKillContribu();
        iSilver = stRewardCfg.GetAcademyKillSilver();

        iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
        iTotalRepu += iReputation > 0 ? iReputation : 0;
        iTotalContri += iContribu > 0 ? iContribu : 0;
        iTotalSilver += iSilver > 0 ? iSilver : 0;

        stCmdData.SetKillReputation(iReputation > 0 ? iReputation : 0);
        stCmdData.SetKillExp(iBattleExp > 0 ? iBattleExp : 0);
        stCmdData.SetKillContribu(iContribu > 0 ? iContribu : 0);
        stCmdData.SetKillSilver(iSilver > 0 ? iSilver : 0);
    }

    CDropItem stDropItem;
    AcademyBossRewardItem(stPlayerCache._uiGID, iTotalRepu, iTotalExp,
        iTotalContri, iTotalSilver, stDropItem);

    stDropItem.GetPBMsg(stPlayerCache._uiGID, *(stAns.mutable_battle_award()));

    CTSizeString<ROLENAME_LEN> szNameStr;
    MsgTips stTips;
    stTips.set_type(TIPS_ACADEMY_BOSS_BONUS);
    szNameStr.Set("%d",stAcademyMon.GetAtkValue());//伤害
    stTips.add_tip_argument(szNameStr());
    stDropItem.GetPBMsg(stPlayerCache._uiGID, *(stTips.mutable_bonus()));

    CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerCache._uiGID, ID_MAIN_TIPS,
        stTips, false);

    return 0;
}

int CAcademyBossMgr::AcademyBossFinishReward(int iAcademyType)
{
    int iRet = 0;
    int iIndex = 0;
    int iAttackAcademy = 0;

    if (!IsValidAcademyType(iAcademyType))
    {
        return ERROR_ACADEMY_BOSS_ACADEMY_TYPE;
    }

    iIndex = _stRandList.FindAcademyRand(iAcademyType);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_ACADEMY_TYPE);

    iAttackAcademy = _stRandList.GetAcademyRand(iIndex);

    iIndex = _stMonList.FindAcademyMon(iAttackAcademy);
    CT_CHECK(iIndex, ERROR_ACADEMY_BOSS_MON_EMPTY);

    CAcademyBossMonster& stAcademyMon = _stMonList.GetAcademyMon(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stWorldBossMgr.FindRewardConfig(
        stAcademyMon.GetWorldLevel());
    if (iIndex < 0)
    {
        CT_WARNING(("academy boss world level(%d) cfg empty",
                    stAcademyMon.GetWorldLevel()));
        return 0;
    }

    CWorldBossCfgReward& stRewardCfg =
        CMainCtrl::m_pstMain->m_stWorldBossMgr.GetRewardConfig(iIndex);

    unsigned int uiGiftID = 0;
    for (int i = 0; i < stAcademyMon.GetRankSize() &&
           i < stRewardCfg.GetAcademyGiftSize(); ++i)
    {
        CAcademyBossAtkUnit& stAtkUnit = stAcademyMon.GetRankUnit(i);
        uiGiftID = (unsigned int)stRewardCfg.GetAcademyGiftID(i);

        CT_TRACE(("world boss reward atk rank(%d) role(%u) gift(%u)",
                  i,stAtkUnit.GetGID(),uiGiftID));
        if (uiGiftID > 0)
        {
            iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropBonus(OSS_MODULE_ADMBOSS,
                stAtkUnit.GetGID(), uiGiftID, 1);
            if (iRet)
            {
                CT_ERROR(("academy boss send role(%u) gift(%u) error(%d)",
                    stAtkUnit.GetGID(),uiGiftID,iRet));
            }
        }
    }

    return 0;
}

